package com.server.util;

import javax.net.ssl.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * http请求类
 * 	String body = HttpUtils.connect("http://www.baidu.com")
 * 				.setMethod("GET")
 * 				.setCharset("UTF-8")
 * 				.execute()
 * 				.getBody();
 * 		System.out.println(body);
 *        }
 */
public class HttpUtils {
	private static Map<String,Object> map=new ConcurrentHashMap<>();

	/**
	 * https post请求
	 * @param url 地址
	 * @param params 参数
	 * @param type 1表单2json3*\/*
	 * @return 返回结果
	 * @throws Exception
	 */
	public static String sendHttpsPost(String url, String params, String type) throws Exception {
		if (type.equals("1")){
			type="application/x-www-form-urlencoded;charset=UTF-8";
		}else if (type.equals("2")){
			type="application/json";
		}else if (type.equals("3")){
			type="*/*";
		}
		DataOutputStream out = null;
		BufferedReader in = null;
		StringBuffer result = new StringBuffer();
		URL u = null;
		HttpsURLConnection con = null;
		// 尝试发送请求
		try {
			SSLContext sc = SSLContext.getInstance("SSL");
			sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
			u = new URL(url);
			// 打开和URL之间的连接
			con = (HttpsURLConnection) u.openConnection();
			// 设置通用的请求属性
			con.setSSLSocketFactory(sc.getSocketFactory());
			con.setHostnameVerifier(new TrustAnyHostnameVerifier());
			// con.setRequestMethod("POST");
			con.setRequestProperty("Content-Type", type); //
			con.setUseCaches(false);
			// 发送POST请求必须设置如下两行
			con.setDoOutput(true);
			con.setDoInput(true);

			con.connect();
			out = new DataOutputStream(con.getOutputStream());
			out.write(params.getBytes("utf-8"));
			// 刷新、关闭
			out.flush();
			out.close();
			// 读取返回内容
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
			String line;
			while ((line = in.readLine()) != null) {
				result.append(line).append(System.lineSeparator());
			}
			return result.toString();
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
		// 使用finally块来关闭输出流、输入流
		finally {
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
				if (con != null) {
					con.disconnect();
				}
			} catch (IOException ex) {
				throw new Exception(ex.getMessage());
			}
		}
	}

	private static class TrustAnyTrustManager implements X509TrustManager {

		public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		}

		public X509Certificate[] getAcceptedIssuers() {
			return new X509Certificate[] {};
		}

	}

	private static class TrustAnyHostnameVerifier implements HostnameVerifier {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	}
	private HttpURLConnection connection;
	private Charset charset = Charset.forName("UTF-8");
	private int readTimeout = 32000;
	private int connectTimeout = 10000;
	private String method = "GET";
	private boolean doInput = true;
	private Map<String, Object> headers = null;
	private String data = null;

	/**
	 * 入口
	 * @param url 地址
	 * @return 结果
	 * @throws IOException
	 */
	public static HttpUtils connect(String url) throws IOException {
		return new HttpUtils((HttpURLConnection) new URL(url).openConnection());
	}

	/**
	 * 禁止new实例
	 */
	private HttpUtils() {
	}

	private HttpUtils(HttpURLConnection connection) {
		this.connection = connection;
	}

	/**
	 * 设置读去超时时间/ms
	 *
	 * @param timeout
	 */
	public HttpUtils setReadTimeout(int timeout) {
		this.readTimeout = timeout;
		return this;
	}

	/**
	 * 设置链接超时时间/ms
	 *
	 * @param timeout
	 */
	public HttpUtils setConnectTimeout(int timeout) {
		this.connectTimeout = timeout;
		return this;
	}

	/**
	 * 设置请求方式
	 *
	 * @param method
	 */
	public HttpUtils setMethod(String method) {
		this.method = method;
		return this;
	}

	/**
	 * 添加Headers
	 *
	 * @param map
	 */
	public HttpUtils setHeaders(Map<String, Object> map) {
		String cookie = "Cookie";
		if (map.containsKey(cookie)) {
			headers = new HashMap<String, Object>();
			headers.put(cookie, map.get(cookie).toString());
		}
		return this;
	}

	/**
	 * 是否接受输入流
	 * 默认true
	 *
	 * @param is
	 */
	public HttpUtils setDoInput(boolean is) {
		this.doInput = is;
		return this;
	}

	/**
	 * 设置请求响应的编码
	 */
	public HttpUtils setCharset(String charset) {
		this.charset = Charset.forName(charset);
		return this;
	}

	/**
	 *@param object  写入数据,接受Map<String,String>或String类型<br>
	 * 例如POST时的参数<br>
	 * demo=1&name=2
	 */
	public HttpUtils setData(Object object) {
		if (object == null) {
			return this;
		} else if (object instanceof String) {
			this.data = (String) object;
		} else if (object instanceof Map) {
			Map map = (Map) object;
			StringBuilder builder = new StringBuilder();
			for (Object key : map.keySet()) {
				builder.append(key + "=" + map.get(key) + "&");
			}
			this.data = builder.toString().substring(0, builder.length() > 0 ? builder.length() - 1 : builder.length());
		}
		return this;
	}

	/**
	 * 发起请求
	 */
	public HttpUtils execute() throws IOException {
		//添加请求头
		if (headers != null) {
			for (String key : headers.keySet()) {
				connection.setRequestProperty(key, headers.get(key).toString());
			}
		}
		//设置读去超时时间为10秒
		connection.setReadTimeout(readTimeout);
		//设置链接超时为10秒
		connection.setConnectTimeout(connectTimeout);
		//设置请求方式,GET,POST
		connection.setRequestMethod(method.toUpperCase());
		//接受输入流
		connection.setDoInput(doInput);
		//写入参数
		if (data != null && !method.equalsIgnoreCase("GET")) {
			//启动输出流，当需要传递参数时需要开启
			connection.setDoOutput(true);
			//添加请求参数，注意：如果是GET请求，参数要写在URL中
			OutputStream output = connection.getOutputStream();
			BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(output, charset));
			//写入参数 用&分割。
			writer.write(data);
			writer.flush();
			writer.close();
		}
		//发起请求
		connection.connect();
		return this;
	}

	/**
	 * 获取HttpURLConnection
	 */
	public HttpURLConnection getConnection() {
		return this.connection;
	}

	/**
	 * 获取响应字符串
	 */
	public String getBody(String... charsets) {
		String charset = "UTF-8";
		if (charsets.length > 0) {
			charset = charsets[0];
		}
		try {
			InputStream inputStream = connection.getInputStream();
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, charset));
			String line = bufferedReader.readLine();
			StringBuilder builder = new StringBuilder();
			while (line != null) {
				builder.append(line);
				line = bufferedReader.readLine();
			}
			return builder.toString();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
	/**
	 * 从request中获得参数Map，并返回可读的Map
	 *
	 * @param request
	 * @return
	 */
	public static SortedMap getParameterMap(HttpServletRequest request) {
		// 参数Map
		Map properties = request.getParameterMap();
		// 返回值Map
		SortedMap returnMap = new TreeMap();
		Iterator entries = properties.entrySet().iterator();
		Map.Entry entry;
		String name = "";
		String value = "";
		while (entries.hasNext()) {
			entry = (Map.Entry) entries.next();
			name = (String) entry.getKey();
			Object valueObj = entry.getValue();
			if (null == valueObj) {
				value = "";
			} else if (valueObj instanceof String[]) {
				String[] values = (String[]) valueObj;
				for (int i = 0; i < values.length; i++) {
					value = values[i] + ",";
				}
				value = value.substring(0, value.length() - 1);
			} else {
				value = valueObj.toString();
			}
			returnMap.put(name, value.trim());
		}
		return returnMap;
	}



	/**
	 * 获取客户端IP
	 */
	public static String getIp(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}
/**
 * @Author 卧夜听风雨
 * @Description 解决跨域问题
 * @Date 2019/2/27
 * @Param [response]
 * @return javax.servlet.http.HttpServletResponse
 **/
	public static HttpServletResponse getAcc(HttpServletResponse response){
		response.setHeader("Access-Control-Allow-Origin", "*");
		return response;
	}
}